﻿#region
using System;
using System.ComponentModel;
using System.Diagnostics;
using System.Drawing;
using System.IO;
using System.Net;
using System.Windows.Forms;
using Y2M.Components;
using Y2M.Properties;
using YoutubeExtractor;

#endregion

namespace Y2M.Controls
{
    public partial class ItemControl : UserControl
    {
        private ItemControl()
        {
            InitializeComponent();

            _worker.WorkerReportsProgress = true;
            _worker.DoWork += Worker_DoWork;
            _worker.ProgressChanged += Worker_ProgressChanged;
            _worker.RunWorkerCompleted += Worker_RunWorkerCompleted;
        }

        public ItemControl(string url) : this()
        {
            Url = url;
        }

        public string Url { get; private set; }

        public bool Finished { get; private set; }

        private readonly BackgroundWorker _worker = new BackgroundWorker();

        protected override void OnLoad(EventArgs e)
        {
            base.OnLoad(e);

            if (DesignMode || RunTimeChecker.IsRunTime == false)
                return;

            _worker.RunWorkerAsync(Url);
        }

        private void Worker_ProgressChanged(object sender, ProgressChangedEventArgs e)
        {
            switch ((ReportPhase) e.ProgressPercentage)
            {
                case ReportPhase.Title:
                    lblTitle.Text = (string) e.UserState;
                    break;
                case ReportPhase.Thumbnail:
                    ptbThumbnail.Image = (Image) e.UserState;
                    break;
                case ReportPhase.Finish:
                    lblTitle.Font = new Font(lblTitle.Font, FontStyle.Strikeout);
                    prbProgress.Visible = false;
                    Finished = true;
                    break;
            }
        }

        private void Worker_DoWork(object sender, DoWorkEventArgs e)
        {
            string url = (string) e.Argument;

            ClipInfo clip = YoutubeHelper.GetClipInfoFromUrl(url);

            if (clip == null)
            {
                e.Result = this;
                return;
            }

            _worker.ReportProgress((int) ReportPhase.Title, clip.Title);

            var image = LoadImage(clip.ThumbnailUrl);
            _worker.ReportProgress((int) ReportPhase.Thumbnail, image);

            string videoPath = DownloadVideo(clip);

            if (Settings.Default.AudioOnly)
                ConvertToAudio(clip, videoPath);

            _worker.ReportProgress((int) ReportPhase.Finish);
        }

        private void Worker_RunWorkerCompleted(object sender, RunWorkerCompletedEventArgs e)
        {
            if (e.Result != null)
                OnWrongClipCopied((ItemControl) e.Result);
        }

        private void ConvertToAudio(ClipInfo clipInfo, string videoPath)
        {
            string audioPath = Path.Combine(Settings.Default.DownloadRoot, clipInfo.Title + ".mp3");

            string argument = string.Format(@"-i ""{0}"" -vn -f mp3 ""{1}""", videoPath, audioPath);

            Process process = new Process();
            process.StartInfo = new ProcessStartInfo("ffmpeg.exe", argument);
            process.StartInfo.UseShellExecute = false;
            process.StartInfo.RedirectStandardOutput = true;
            process.StartInfo.CreateNoWindow = true;
            process.Start();
            process.WaitForExit();

            File.Delete(videoPath);
        }

        private string DownloadVideo(ClipInfo clipInfo)
        {
                string videoPath = Path.Combine(Settings.Default.DownloadRoot, clipInfo.Title + clipInfo.VideoExtension);

                var videoDownloader = new VideoDownloader(clipInfo.VideoInfo, videoPath);
                videoDownloader.DownloadProgressChanged += VideoDownloader_DownloadProgressChanged;
                videoDownloader.Execute();

                return videoPath;
        }

        private void VideoDownloader_DownloadProgressChanged(object sender, ProgressEventArgs e)
        {
            this.InvokeIfNeeded(() => prbProgress.Value = (int) e.ProgressPercentage);
        }

        private Image LoadImage(string url)
        {
            WebClient webClient = new WebClient();
            var bytes = webClient.DownloadData(url);

            using (var stream = new MemoryStream(bytes))
            {
                return new Bitmap(stream);
            }
        }

        private enum ReportPhase
        {
            Title,
            Thumbnail,
            Download,
            Convert,
            Finish
        }

        #region WrongClipCopied event things for C# 3.0
        public event EventHandler<WrongClipCopiedEventArgs> WrongClipCopied;

        protected virtual void OnWrongClipCopied(WrongClipCopiedEventArgs e)
        {
            if (WrongClipCopied != null)
                WrongClipCopied(this, e);
        }

        protected virtual void OnWrongClipCopied(ItemControl itemControl)
        {
            OnWrongClipCopied(new WrongClipCopiedEventArgs(itemControl));
        }

        protected virtual WrongClipCopiedEventArgs OnWrongClipCopiedWithReturn(ItemControl itemControl)
        {
            WrongClipCopiedEventArgs args = new WrongClipCopiedEventArgs(itemControl);
            OnWrongClipCopied(args);

            return args;
        }

        public class WrongClipCopiedEventArgs : EventArgs
        {
            public ItemControl ItemControl { get; set; }

            public WrongClipCopiedEventArgs()
            {
            }

            public WrongClipCopiedEventArgs(ItemControl itemControl)
            {
                ItemControl = itemControl;
            }
        }
        #endregion
    }
}